package xyz.ibenben.zhongdian.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Date工具类
 * 处理时间的工具类，包含根据所给日期获取当天的00:00:00、根据所给日期获取当天的23:59:59等方法
 * 项目内所有和时间有关的方法都出自此类
 *
 * @author chenjian
 * @since 2017年10月18日下午5:17:22
 */
public class DateUtils {
    private DateUtils() {
    }

    /**
     * 根据所给日期获取当天的00:00:00
     *
     * @param date 参数
     * @return 返回值
     */
    public static Date getStartDate(Date date) {
        if (date != null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            return cal.getTime();
        }
        return null;
    }

    /**
     * 根据所给日期获取当天的23:59:59
     *
     * @param date 参数
     * @return 返回值
     */
    public static Date getEndDate(Date date) {
        if (date != null) {
            Date startDate = getStartDate(date);
            Calendar cal = Calendar.getInstance();
            cal.setTime(startDate);
            cal.add(Calendar.HOUR_OF_DAY, 23);
            cal.add(Calendar.MINUTE, 59);
            cal.add(Calendar.SECOND, 59);
            return cal.getTime();
        }
        return null;
    }

    /**
     * 根据所给日期获取30天后的日期
     *
     * @param date 参数
     * @return 返回值
     */
    public static Date getNextMonthDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH, 30);
        return cal.getTime();
    }

    /**
     * 取得指定月份的最后一天
     *
     * @param date 参数
     * @return 返回值
     */
    public static int getMonthEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 取得当月的日
     *
     * @param date 参数
     * @return 返回值
     */
    public static int getNowDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DATE);// 获取日
    }

    /**
     * 获取上个月的日期
     *
     * @param date 参数
     * @return 返回值
     */
    public static Date getLastMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, -1);
        return cal.getTime();
    }

    /**
     * 获取下个月的第一天
     *
     * @param date 参数
     * @return 返回值
     */
    public static Date getNextMonthFirstDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, 1);
        cal.set(Calendar.DATE, 1);
        return cal.getTime();
    }

    /**
     * 获取下个月的最后一天
     *
     * @param date 参数
     * @return 返回值
     */
    public static Date getNextMonthLastDay(Date date) {
        Date lastMonth = getNextMonthFirstDay(date);
        Calendar cal = Calendar.getInstance();
        cal.setTime(lastMonth);
        cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
        return cal.getTime();
    }

    /**
     * 获取当前的时间
     *
     * @param date   日期
     * @param format 参数
     * @return 返回值
     */
    public static String getCurrentTime(Date date, String format) {
        Date newDate = new Date();
        if (date != null) {
            newDate = date;
        }
        return new SimpleDateFormat(format).format(newDate);
    }

    /**
     * 获取前一天日期
     *
     * @param format 参数
     * @return 返回值
     */
    public static String getYestoday(String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        return new SimpleDateFormat(format).format(calendar.getTime());
    }

    /**
     * 功能：将制定日期的秒数进行重新设置。
     *
     * @param date   日期
     * @param second 秒数
     * @return 设置后的日期
     */
    public static Date setSecondNew(Date date, int second) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.SECOND, second);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：将制定日期的分钟进行重新设置。
     *
     * @param date   日期
     * @param minute 分钟数
     * @return 设置后的日期
     */
    public static Date setMinuteNew(Date date, int minute) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.MINUTE, minute);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：将制定日期的小时进行重新设置。
     *
     * @param date 参数
     * @param hour 参数
     * @return 返回值
     */
    public static Date setHourNew(Date date, int hour) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, hour);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：将制定日期的天进行重新设置。
     *
     * @param date 参数
     * @param day  参数
     * @return 返回值
     */
    public static Date setDayNew(Date date, int day) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DATE, day);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：将制定日期的月进行重新设置。
     *
     * @param date  参数
     * @param month 参数
     * @return 返回值
     */
    public static Date setMonthNew(Date date, int month) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.MONTH, month - 1);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：将制定日期的年进行重新设置。
     *
     * @param date 参数
     * @param year 参数
     * @return 返回值
     */
    public static Date setYearNew(Date date, int year) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.YEAR, year);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：得到制定月有多少天。
     *
     * @param date
     * @return int
     */
    public static int daysNumOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.getActualMaximum(Calendar.DATE);
    }

    /**
     * 将yyyy-MM-dd HH:mm:ss字符串转换成日期
     *
     * @param dateStr yyyy-MM-dd HH:mm:ss字符串
     * @param format  格式
     * @return net.maxt.util.Date 日期 ,转换异常时返回null。
     */
    public static Date parseDate(String dateStr, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            Date d = sdf.parse(dateStr);
            return new Date(d.getTime());
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 功能：计算两个时间的时间差。
     *
     * @param time 另一个时间。
     * @return Timespan 时间间隔
     */
    public static long substract(Date time) {
        return new Date().getTime() - time.getTime();
    }

    /**
     * 功能：制定时间增加秒数。
     *
     * @param date    日期
     * @param seconds 正值时时间延后，负值时时间提前。
     * @return Date
     */
    public static Date addSeconds(Date date, int seconds) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.SECOND, c.get(Calendar.SECOND) + seconds);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：制定时间增加分钟数。
     *
     * @param date    日期
     * @param minutes 正值时时间延后，负值时时间提前。
     * @return Date
     */
    public static Date addMinutes(Date date, int minutes) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + minutes);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：制定时间增加小时数。
     *
     * @param date  日期
     * @param hours 正值时时间延后，负值时时间提前。
     * @return Date
     */
    public static Date addHours(Date date, int hours) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR, c.get(Calendar.HOUR) + hours);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：制定时间增加天数。
     *
     * @param date 日期
     * @param days 正值时时间延后，负值时时间提前。
     * @return Date
     */
    public static Date addDays(Date date, int days) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DATE, c.get(Calendar.DATE) + days);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：制定时间增加月数。
     *
     * @param date   日期
     * @param months 正值时时间延后，负值时时间提前。
     * @return Date
     */
    public static Date addMonths(Date date, int months) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.MONTH, c.get(Calendar.MONTH) + months);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 功能：制定时间增加年数。注意遇到2月29日情况，系统会自动延后或者减少一天。
     *
     * @param date  日期
     * @param years 正值时时间延后，负值时时间提前。
     * @return Date
     */
    public static Date addYears(Date date, int years) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.YEAR, c.get(Calendar.YEAR) + years);
        return new Date(c.getTimeInMillis());
    }

    /**
     * 根据制定日期得到星期几,得到数字。
     * 7, 1, 2, 3, 4, 5, 6
     *
     * @param date 日期
     * @return Integer 如：6
     */
    public static int dayOfWeekInt(Date date) {
        Integer[] dayNames = {7, 1, 2, 3, 4, 5, 6};
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        if (dayOfWeek < 0)
            dayOfWeek = 0;
        return dayNames[dayOfWeek];
    }

    /**
     * 根据日期返回对应corn表达式字符串
     * 例如 0 58 11 2 4 ? 2018
     *
     * @param date 日期
     * @return 根据日期返回corn
     */
    public static String translation(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DATE);
        int hour = calendar.get(Calendar.HOUR);
        int min = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        return second + " " + min + " " + hour + " " + day + " " + month + " ? " + year;
    }
}
